<style lang="scss" scoped>
.image-input-container {

	width: 100%;

	.multiple {
		display: flex;
		flex-wrap: wrap;
		align-items: center;

		&-item {
			line-height: 0;
			position: relative;
			margin: 0 10px 10px 0;
			width: var(--image-size);
			height: var(--image-height);
			overflow: hidden;
			border-radius: var(--radius-size);
			border: 1px solid rgba(0, 0, 0, 0.3);

			&.uploading,
			&.uploader {
				border: 1px dashed rgba(0, 0, 0, 0.3);
				display: flex;
				align-items: center;
				justify-content: center;
			}

			.remove {
				width: var(--size);
				height: var(--size);
				border-radius: var(--radius-size);
				display: flex;
				align-items: center;
				justify-content: center;
				z-index: 120;
				box-shadow: 0 0 5px rgb(127, 127, 127);
				background-color: #08080838;
				position: absolute;
				right: 3px;
				top: 3px;

				&::before {
					content: "";
					position: absolute;
					width: var(--size);
					height: var(--size);
					filter: blur(30px);
					z-index: 119;
				}
			}
		}

		.uploader {
			margin-bottom: 10px;
		}
	}

	.multiple {
		.image {
			border: none;
			border-radius: 0;
		}
	}

	.image {
		width: var(--image-size);
		height: var(--image-height);
		border-radius: var(--radius-size);
		border: 1px solid rgba(0, 0, 0, 0.3);
		overflow: hidden;

		:deep(.el-image__error) {
			height: var(--image-height);
		}
	}

	.image-default {
		font-size: 28px;
		color: #8c939d;
		width: var(--image-size);
		height: var(--image-height);
		border: 1px dashed #d9d9d9;
		border-radius: var(--radius-size);
		line-height: var(--image-height);
		text-align: center;
	}

	.image-default:hover {
		border-color: #409eff;
	}
}
</style>

<template>
	<div class="image-input-container" :style="{
		'--image-size': size + 'px',
		'--radius-size': radius + 'px',
		'--image-height': (height ? height : size) + 'px',
	}">
		<!-- 文件多选 -->
		<div v-if="multiple" class="multiple">
			<div class="multiple-item" v-for="(image, idx) in imageList" :key="idx">
				<div v-if="!props.disabled" class="remove" @click="remove(idx)" :style="{ '--size': (closeBtnSize + 5) + 'px' }">
					<div class="btn">
						<el-icon :size="(closeBtnSize)" color="#ffffff">
							<Close />
						</el-icon>
					</div>
				</div>
				<el-image :src="image" fit="cover" class="image" :preview-src-list="imageList" />
			</div>
			<div class="multiple-item uploading" v-for="idx in uploadChannel" :key="idx">
				<el-icon :size="size * 0.25" class="is-loading" color="#8c939d">
					<Loading />
				</el-icon>
			</div>
			<div v-show="!props.disabled && uploadLimit > 0" class="multiple-item uploader">
				<el-upload ref="uploader" action multiple :limit="uploadLimit" :on-exceed="exceed" :accept="accept"
					:http-request="upload" :before-upload="beforeUpload" :show-file-list="false">
					<div style="display: flex;justify-content: center;align-items: center;" :style="{
						width: size + 'px', height: (height ? height : size) + 'px',
					}">
						<el-icon :size="size * 0.3" color="#8c939d">
							<Plus />
						</el-icon>
					</div>
				</el-upload>
			</div>
		</div>

		<!-- 文件单选 -->
		<div v-else class="singular">
			<el-input v-if="networkUrl" v-model="imageLink" :placeholder="placeholder" clearable @input="UrlInput" />
			<el-upload class="uploader" ref="uploader" :show-file-list="false" action :accept="accept"
				:http-request="upload" :before-upload="beforeUpload">
				<el-image v-if="!uploading && imageLink" :src="imageLink" class="image" fit="cover" />
				<div v-else class="image-default">
					<el-icon :size="closeBtnSize" :class="[uploading ? 'is-loading' : '']">
						<Loading v-if="uploading" />
						<Plus v-else />
					</el-icon>
				</div>
			</el-upload>
		</div>
	</div>
</template>

<script setup>

import { ElMessage } from "element-plus";
import { ref, inject, computed, watch } from 'vue';
import { Close, Plus, Loading } from '@element-plus/icons-vue'

const http = inject('$http'),
	tools = inject('$tools');

const model = defineModel({ type: [String, Array] });
const closeBtnSize = 20,
	uploader = ref(),
	imageLink = ref(""),
	imageList = ref([]),
	uploadChannel = ref([]),
	uploading = ref(false);

const props = defineProps({
	networkUrl: {
		type: Boolean,
		default: true,
	},
	placeholder: {
		type: String,
		default: "链接地址",
	},
	business: {
		type: String,
		default: "image",
	},
	size: {
		type: Number,
		default: 120,
	},
	height: Number,
	multiple: {
		type: Boolean,
		default: false,
	},
	limit: {
		type: Number,
		default: 9,
	},
	accept: {
		type: String,
		default: "image/PNG,image/JPEG,image/JPG"
	},
	full_path: {
		type: Boolean,
		default: false
	},
	radius: {
		type: Number,
		default: 10
	},
	disabled:{
		type: Boolean,
		default: false
	}
})

const uploadLimit = computed(() => {
	try {
		let limit = props.limit - imageList.value.length - uploadChannel.value.length;
		if (limit < 0) limit = 0;
		return limit;
	} catch (err) {
		return props.limit;
	}
})

watch(model, (nv) => {
	if (props.multiple) {
		imageList.value = nv;
	} else {
		imageLink.value = nv;
	}
})

function beforeUpload(file) {
	return tools.imageValidate(file);
}

async function upload(file) {
	console.log(file);
	uploadChannel.value.push(file.file.uid);
	uploading.value = true;
	const res = await http.uploadImage(file.file, props.business);
	setTimeout(() => {
		uploading.value = false;
		uploadChannel.value.pop();
		if (res && res.code === 200) {
			const value = props.full_path ? res.data.full_path : res.data.path;
			if (props.multiple) {
				if (typeof imageList.value !== 'object') imageList.value = [];
				imageList.value.push(value);
			} else {
				imageLink.value = value;
			}
			transferToParent();
		} else {
			tools.httpFaildHandler(res, 'warning')
		}
	}, Math.random() * 1000);
	uploader.value.clearFiles();
}

function UrlInput(value) {
	imageLink.value = value;
	transferToParent();
}

function transferToParent() {
	model.value = props.multiple ? imageList.value : imageLink.value;
}

function remove(index) {
	imageList.value.splice(index, 1);
}

function exceed() {
	ElMessage({ message: `最多还可以选择${uploadLimit.value} 个文件` });
}

if (props.multiple) {
	imageList.value = model.value ? model.value : [];
} else {
	imageLink.value = model.value;
}

</script>
